package com.campus.schedule.timer;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.campus.schedule.entity.UserCoupon;
import com.campus.schedule.service.UserCouponService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 用户优惠券状态定时任务服务
 *
 * @author TraeAI
 * @since 2024-07-30
 */
@Service
@Slf4j
public class UserCouponStatusScheduleService {

    @Autowired
    private UserCouponService userCouponService;

    /**
     * 每分钟检查并更新用户优惠券状态
     * <p>
     * 1. 未生效 -> 可用：当 status=0 且当前时间 >= useStartTime
     * 2. 可用 -> 已过期：当 status=1 且当前时间 >= useEndTime
     */
    @Scheduled(cron = "0 5 0 * * ?") // 每天凌晨00:05执行一次
    public void updateUserCouponStatus() {
        log.info("开始执行用户优惠券状态更新定时任务...");
        LocalDateTime now = LocalDateTime.now();
        int updatedCount = 0;

        // 1. 处理 "未生效" -> "可用"
        try {
            LambdaQueryWrapper<UserCoupon> toAvailableQuery = new LambdaQueryWrapper<>();
            toAvailableQuery.eq(UserCoupon::getStatus, 0) // 状态为0：未生效
                    .le(UserCoupon::getUseStartTime, now); // 当前时间 >= 使用开始时间

            List<UserCoupon> toAvailableCoupons = userCouponService.list(toAvailableQuery);
            if (!toAvailableCoupons.isEmpty()) {
                log.info("发现 {} 张优惠券从未生效变为可用", toAvailableCoupons.size());
                for (UserCoupon coupon : toAvailableCoupons) {
                    try {
                        updateCouponStatusToAvailable(coupon.getId());
                        updatedCount++;
                        log.debug("优惠券ID: {} 状态更新为可用", coupon.getId());
                    } catch (Exception e) {
                        log.error("更新优惠券ID: {} 状态为可用失败: {}", coupon.getId(), e.getMessage(), e);
                        // 继续处理下一张优惠券，不中断整个任务
                    }
                }
            }
        } catch (Exception e) {
            log.error("查询待更新为可用的优惠券失败", e);
        }

        // 2. 处理 "可用" -> "已过期"
        try {
            LambdaQueryWrapper<UserCoupon> toExpiredQuery = new LambdaQueryWrapper<>();
            toExpiredQuery.eq(UserCoupon::getStatus, 1) // 状态为1：可用
                    .le(UserCoupon::getUseEndTime, now); // 当前时间 >= 使用结束时间

            List<UserCoupon> toExpiredCoupons = userCouponService.list(toExpiredQuery);
            if (!toExpiredCoupons.isEmpty()) {
                log.info("发现 {} 张优惠券从可用变为已过期", toExpiredCoupons.size());
                for (UserCoupon coupon : toExpiredCoupons) {
                    try {
                        updateCouponStatusToExpired(coupon.getId());
                        updatedCount++;
                        log.debug("优惠券ID: {} 状态更新为已过期", coupon.getId());
                    } catch (Exception e) {
                        log.error("更新优惠券ID: {} 状态为已过期失败: {}", coupon.getId(), e.getMessage(), e);
                        // 继续处理下一张优惠券，不中断整个任务
                    }
                }
            }
        } catch (Exception e) {
            log.error("查询待更新为已过期的优惠券失败", e);
        }

        if (updatedCount > 0) {
            log.info("用户优惠券状态更新定时任务执行完毕，共更新 {} 张优惠券状态", updatedCount);
        } else {
            log.info("用户优惠券状态更新定时任务执行完毕，无优惠券状态变更");
        }
    }

    /**
     * 更新优惠券状态为可用
     * 使用独立事务，确保单个优惠券失败不影响其他优惠券
     * 
     * @param couponId 优惠券ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateCouponStatusToAvailable(Integer couponId) {
        LambdaUpdateWrapper<UserCoupon> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(UserCoupon::getId, couponId)
                .set(UserCoupon::getStatus, 1); // 更新状态为1：可用
        
        boolean updateSuccess = userCouponService.update(updateWrapper);
        if (!updateSuccess) {
            throw new RuntimeException("更新优惠券状态为可用失败");
        }
    }

    /**
     * 更新优惠券状态为已过期
     * 使用独立事务，确保单个优惠券失败不影响其他优惠券
     * 
     * @param couponId 优惠券ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateCouponStatusToExpired(Integer couponId) {
        LambdaUpdateWrapper<UserCoupon> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(UserCoupon::getId, couponId)
                .set(UserCoupon::getStatus, 3); // 更新状态为3：已过期
        
        boolean updateSuccess = userCouponService.update(updateWrapper);
        if (!updateSuccess) {
            throw new RuntimeException("更新优惠券状态为已过期失败");
        }
    }
}